/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.message.service.wechat.impl;

import cn.hutool.core.io.FileUtil;
import com.je.common.base.constants.message.WxMessageType;
import com.je.common.base.constants.message.WxTwType;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.MessageUtils;
import com.je.common.base.util.StringUtil;
import com.je.message.Push;
import com.je.message.ResultMsgResp;
import com.je.message.exception.MessageSendException;
import com.je.message.service.AbstractThirdPartyPush;
import com.je.message.service.log.LogServiceFactory;
import com.je.message.vo.MessageVo;
import com.je.message.service.wechat.WeChatMsgService;
import com.je.meta.util.SettingHelper;
import com.je.meta.util.setting.Open.OpenWeChat;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpMessage;
import me.chanjar.weixin.cp.bean.WxCpMessageSendResult;
import me.chanjar.weixin.cp.bean.article.MpnewsArticle;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Service
public class WeChatMsgServiceImpl extends AbstractThirdPartyPush implements WeChatMsgService {

    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;

    @Override
    public ResultMsgResp send(MessageVo msgVo)  {
        //根据不同类型发送
        if (WxMessageType.WZ.equals(msgVo.getMsgType())) {
            return sendWz(msgVo.getUserIds(), msgVo.getContent());
        } else if (WxMessageType.TW.equals(msgVo.getMsgType())) {
            return sendTw(msgVo.getUserIds(), msgVo.getMsgType(), msgVo.getTwType(), msgVo.getTitle(),
                    msgVo.getAuthor(), msgVo.getRemark(), msgVo.getContent(), msgVo.getFileKey());
        } else if (WxMessageType.TP.equals(msgVo.getMsgType())) {
            return sendTp(msgVo.getUserIds(), msgVo.getFileKey());
        } else if (WxMessageType.YY.equals(msgVo.getMsgType())) {
            return sendYy(msgVo.getUserIds(), msgVo.getFileKey());
        } else if (WxMessageType.SP.equals(msgVo.getMsgType())) {
            return sendSp(msgVo.getUserIds(), msgVo.getFileKey(), msgVo.getTitle(), msgVo.getContent());
        } else if (WxMessageType.WJ.equals(msgVo.getMsgType())) {
            return sendWj(msgVo.getUserIds(), msgVo.getFileKey());
        }

        return new ResultMsgResp(9999, MessageUtils.getMessage("message.sendMsgType.notExits"), false);
    }

    private ResultMsgResp saveLog(MessageVo msgVo, WxCpService wxCpService, WxCpMessage wxCpMsg) {
        if (wxCpMsg == null) {
            return new ResultMsgResp(90005, "消息推送失败!", false);
        }
        String errorMessage = null;
        WxCpMessageSendResult sendResult = null;
        try {
            sendResult = wxCpService.messageSend(wxCpMsg);
        } catch (WxErrorException e) {
            e.printStackTrace();
            errorMessage = e.getMessage();
            logger.error("Send email failure {}!", errorMessage, msgVo);
        }
        msgVo.setErrorMessage(errorMessage);
        msgVo.setResult(sendResult.getErrMsg());
        LogServiceFactory.newLog(LogServiceFactory.LogTypeEnum.OTHER).saveAllLog(msgVo, Push.WECHAT);
        if (errorMessage != null) {
            return new ResultMsgResp(90005, errorMessage, false);
        }
        return new ResultMsgResp(200, "消息推送成功！", true);
    }


    @Override
    public ResultMsgResp sendWz(String userIds, String context)  {
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.WZ, context);

        //校验系统设置有没有勾选
        checkService(thirdPartyType.WECHAT);
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.DINGTALK);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        wxCpMsg = WxCpMessage.TEXT().agentId(agentId).toUser(sendUserStr).content(msgVo.getContent()).build();
        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    @Override
    public ResultMsgResp sendTw(String userIds, String twType, String title, String context, String picPath, String author, String description, String sourceUrl)  {
        MessageVo msgVo = MessageVo.weChatMsgBuild().setUserIds(userIds).setTwType(WxMessageType.TW).setTitle(title).setAuthor(author)
                .setContent(context).setFileKey(picPath).setAuthor(description).build();
        msgVo.setSourceUrl(sourceUrl);

        //校验系统设置有没有勾选
        checkService(thirdPartyType.WECHAT);
        //人员信息缓存
//        init(msgVo.getUserIds(), "WX");
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.WECHAT);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        MpnewsArticle article = MpnewsArticle.newBuilder().build();
        //标题
        article.setTitle(msgVo.getTitle());
        //作者
        article.setAuthor(msgVo.getAuthor());
        article.setContentSourceUrl(msgVo.getSourceUrl());
        if (WxTwType.HTML.equals(msgVo.getTwType())) {
            article.setContent(context);
        } else if (WxTwType.UEditor.equals(msgVo.getTwType())) {
            context = HtmlUtils.htmlUnescape(context);
            article.setContent(context);
        }
        //内容
        article.setDigest(msgVo.getRemark());
        if (StringUtil.isNotEmpty(msgVo.getFileKey())) {
            File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
            InputStream is = FileUtil.getInputStream(fileBO);
            WxMediaUploadResult uploadMediaRes = null;
            try {
                String suffix = fileBO.getName().substring(fileBO.getName().lastIndexOf("."));
                uploadMediaRes = wxCpService.getMediaService().upload(WxConsts.MediaFileType.IMAGE, suffix, is);
            } catch (Exception e) {
                throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
            }
            article.setThumbMediaId(uploadMediaRes.getMediaId());
        }
        wxCpMsg = WxCpMessage.MPNEWS().agentId(agentId).toUser(sendUserStr).addArticle(article).build();

        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    @Override
    public ResultMsgResp sendTp(String userIds, String filePath)  {
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.TP, "", filePath);

        //校验系统设置有没有勾选
        //人员信息缓存
//        init(msgVo.getUserIds(), "WX");
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.WECHAT);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            return new ResultMsgResp(90001, "图片文件上传失败!", false);
        }
        File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(fileBO);
        WxMediaUploadResult uploadMediaRes = null;
        try {
            String suffix = fileBO.getName().substring(fileBO.getName().lastIndexOf("."));
            uploadMediaRes = wxCpService.getMediaService().upload(WxConsts.MediaFileType.IMAGE, suffix, is);
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new MessageSendException(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (uploadMediaRes == null) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        wxCpMsg = WxCpMessage.IMAGE().agentId(agentId).toUser(sendUserStr).mediaId(uploadMediaRes.getMediaId()).build();

        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    @Override
    public ResultMsgResp sendYy(String userIds, String filePath)  {
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.YY, "", filePath);

        //校验系统设置有没有勾选
        //人员信息缓存
//        init(msgVo.getUserIds(), "WX");
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.WECHAT);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }

        File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(fileBO);
        WxMediaUploadResult uploadMediaRes = null;
        try {
            String suffix = fileBO.getName().substring(fileBO.getName().lastIndexOf("."));
            uploadMediaRes = wxCpService.getMediaService().upload(WxConsts.MediaFileType.VOICE, suffix, is);
        } catch (WxErrorException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (uploadMediaRes == null) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        wxCpMsg = WxCpMessage.VOICE().agentId(agentId).toUser(sendUserStr).mediaId(uploadMediaRes.getMediaId()).build();

        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    @Override
    public ResultMsgResp sendSp(String userIds, String filePath, String title, String description)  {
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.SP, "", filePath);
        msgVo.setTitle(title);
        msgVo.setContent(description);

        //校验系统设置有没有勾选
        //人员信息缓存
//        init(msgVo.getUserIds(), "WX");
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.WECHAT);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(fileBO);
        WxMediaUploadResult uploadMediaRes = null;
        try {
            String suffix = fileBO.getName().substring(fileBO.getName().lastIndexOf("."));
            uploadMediaRes = wxCpService.getMediaService().upload(WxConsts.MediaFileType.VIDEO, suffix, is);
        } catch (WxErrorException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (uploadMediaRes == null) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        wxCpMsg = WxCpMessage.VIDEO().agentId(agentId)
                .toUser(sendUserStr)
                .title(msgVo.getTitle())
                .mediaId(uploadMediaRes.getMediaId())
                .thumbMediaId(uploadMediaRes.getThumbMediaId())
                .description(msgVo.getContent())
                .build();

        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    @Override
    public ResultMsgResp sendWj(String userIds, String filePath)  {
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.WJ, "", filePath);

        //校验系统设置有没有勾选
        //人员信息缓存
//        init(msgVo.getUserIds(), "WX");
        //获取人员信息
        List<String> wxUserIds = getUserIds(msgVo, thirdPartyType.WECHAT);
        //初始化服务
        WxCpService wxCpService = initWxCpService();

        //构建消息信息
        WxCpMessage wxCpMsg = null;
        String sendUserStr = "";
        if ("@all".equals(userIds)) {
            sendUserStr = "@all";
        } else {
            sendUserStr = StringUtil.buildSplitString(ArrayUtils.getArray(wxUserIds), "|");
        }
        int agentId = 0;
        if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
            agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
        }

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(fileBO);
        WxMediaUploadResult uploadMediaRes = null;
        try {
            String suffix = fileBO.getName().substring(fileBO.getName().lastIndexOf("."));
            uploadMediaRes = wxCpService.getMediaService().upload(WxConsts.MediaFileType.FILE, suffix, is);
        } catch (WxErrorException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (uploadMediaRes == null) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        wxCpMsg = WxCpMessage.FILE().agentId(agentId).toUser(sendUserStr).mediaId(uploadMediaRes.getMediaId()).build();

        return saveLog(msgVo, wxCpService, wxCpMsg);
    }

    /**
     * 初始化服务类
     *
     * @return
     */
    private WxCpService initWxCpService() {
        WxCpService wxCpService = null;

            WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
            OpenWeChat openWeChat = SettingHelper.getOpenWeChatConfig();
            // 设置微信企业号的appid
            String corpId = openWeChat.getCorpId();
            // 设置微信企业号的app corpSecret
            String corpSecret = openWeChat.getCorpSecret();
            config.setCorpId(StringUtil.getDefaultValue(corpId, ""));
            config.setCorpSecret(StringUtil.getDefaultValue(corpSecret, ""));
            int agentId = 0;
            if (StringUtil.isNotEmpty(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"))) {
                agentId = Integer.parseInt(systemSettingRpcService.findSettingValue("JE_WXCP_AGENTID"));
            }
            // 设置微信企业号应用ID
            config.setAgentId(agentId);
            // 设置微信企业号应用的token
            config.setToken("...");
            // 设置微信企业号应用的EncodingAESKey
            config.setAesKey("...");
            wxCpService.setWxCpConfigStorage(config);
        return wxCpService;
    }

}
